package com.example.demo.game;

import com.example.demo.DemoApplication;
import com.example.demo.model.User;
import com.example.demo.model.UserMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.UUID;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Wukong
 * Date: 2023-04-24
 * Time: 20:39
 */
public class Room {
    //房间与玩家信息
    private String roomId;
    // 玩家1
    private User user1;
    // 玩家2
    private User user2;
    // 先手方的用户 id
    private int whiteUserId = 0;
    // 棋盘结构 15*15
    //静态常量
    private static final int MAX_ROW = 15;
    private static final int MAX_COL = 15;
    private int[][] chessBoard = new int[MAX_ROW][MAX_COL];

    private ObjectMapper objectMapper = new ObjectMapper();
   @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private RoomManager roomManager;
    @Resource
    private UserMapper userMapper;
    /**
     * 构造方法
     * */
    public Room() {
        // 生成唯一房间ID
        roomId = UUID.randomUUID().toString();

        onlineUserManager = DemoApplication.ac.getBean(OnlineUserManager.class);
//        roomManager = DemoApplication.ac.getBean(RoomManager.class);
//        userMapper = DemoApplication.ac.getBean(UserMapper.class);

        System.out.println("create Room: " + roomId + ", roomManager: " + roomManager);
    }
    // getter / setter 方法略
    public String getRoomId() {
        return roomId;
    }

    public void setRoomId(String roomId) {
        this.roomId = roomId;
    }

    public User getUser1() {
        return user1;
    }

    public void setUser1(User user1) {
        this.user1 = user1;
    }

    public User getUser2() {
        return user2;
    }

    public void setUser2(User user2) {
        this.user2 = user2;
    }

    public int getWhiteUserId() {
        return whiteUserId;
    }

    public void setWhiteUserId(int whiteUserId) {
        this.whiteUserId = whiteUserId;
    }

    public int[][] getChessBoard() {
        return chessBoard;
    }

    public void setChessBoard(int[][] chessBoard) {
        this.chessBoard = chessBoard;
    }

    public ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    public OnlineUserManager getOnlineUserManager() {
        return onlineUserManager;
    }

    public void setOnlineUserManager(OnlineUserManager onlineUserManager) {
        this.onlineUserManager = onlineUserManager;
    }
    /**
     * 落子处理方法
     * */
    public void putChess(String message) throws IOException {
        //通过 ObjectMapper 将客户端发送的 JSON 消息解析为 GameRequest 对象，
        GameRequest req = objectMapper.readValue(message, GameRequest.class);
        GameResponse response = new GameResponse();

        int chess = req.getUserId() == user1.getUserId() ? 1 : 2;// 确定落子玩家（1=玩家1，2=玩家2）
        int row = req.getRow();
        int col = req.getCol();
        if (chessBoard[row][col] != 0) {
            System.out.println("落子位置有误! " + req);
            return;
        }
        //更新棋盘状态
        //chess：表示棋子的值——数字（如 1 代表黑棋，2 代表白棋）
        chessBoard[row][col] = chess;
        printChessBoard();

        //检查游戏胜负
        int winner = checkWinner(chess, row, col);
        // 设置响应数据
        response.setUserId(req.getUserId());//执行落子操作的用户ID
        response.setRow(row);
        response.setCol(col);
        response.setWinner(winner);//胜利玩家的ID
        // 获取两位玩家的 WebSocket 会话
        WebSocketSession session1 = onlineUserManager.getSessionFromGameRoom(user1.getUserId());
        WebSocketSession session2 = onlineUserManager.getSessionFromGameRoom(user2.getUserId());
        if (session1 == null) {
            // 玩家1 掉线, 直接认为玩家2 获胜
            response.setWinner(user2.getUserId());
            System.out.println("玩家1 掉线!");
        }
        if (session2 == null) {
            // 玩家2 掉线, 直接认为玩家1 获胜
            response.setWinner(user1.getUserId());
            System.out.println("玩家2 掉线!");
        }
        //将响应 序列化为 JSON 字符串
        String responseJson = objectMapper.writeValueAsString(response);
        if (session1 != null) {
            session1.sendMessage(new TextMessage(responseJson));
        }
        if (session2 != null) {
            session2.sendMessage(new TextMessage(responseJson));
        }

        if (response.getWinner() != 0) {//胜负已分
            // 更新数据库：获胜方 +1 胜场，失败方 +1 负场
            userMapper.userWin(response.getWinner() == user1.getUserId() ? user1 : user2);
            userMapper.userLose(response.getWinner() == user1.getUserId() ? user2 : user1);
            // 从房间管理器中移除房间
            roomManager.removeRoom(roomId, user1.getUserId(), user2.getUserId());
            System.out.println("游戏结束, 房间已经销毁! roomId: " + roomId + " 获胜方为: " + response.getWinner());
        }
    }
    private void printChessBoard() {
        System.out.println("打印棋盘信息: ");
        System.out.println("===========================");
        for (int r = 0; r < MAX_ROW; r++) {
            for (int c = 0; c < MAX_COL; c++) {
                System.out.print(chessBoard[r][c] + " ");
            }
            System.out.println();
        }
        System.out.println("===========================");
    }
// 判定棋盘形式, 找出胜利的玩家.
// 如果游戏分出胜负, 则返回玩家的 id.
// 如果未分出胜负, 则返回 0
// chess 值为 1 表示玩家1 的落子. 为 2 表示玩家2 的落子
    private int checkWinner(int chess, int row, int col) {
        // 以 row, col 为中心
        boolean done = false;
        // 1. 检查所有的行(循环五次)
        for (int c = col - 4; c <= col; c++) {
            if (c < 0 || c >= MAX_COL) {
                continue;
            }
            if (chessBoard[row][c] == chess
                    && chessBoard[row][c + 1] == chess
                    && chessBoard[row][c + 2] == chess
                    && chessBoard[row][c + 3] == chess
                    && chessBoard[row][c + 4] == chess) {
                done = true;
            }
        }
        // 2. 检查所有的列(循环五次)
        for (int r = row - 4; r <= row; r++) {
            if (r < 0 || r >= MAX_ROW) {
                continue;
            }
            if (chessBoard[r][col] == chess
                    && chessBoard[r + 1][col] == chess
                    && chessBoard[r + 2][col] == chess
                    && chessBoard[r + 3][col] == chess
                    && chessBoard[r + 4][col] == chess) {
                done = true;
            }
        }
        // 3. 检查左对角线
        for (int r = row - 4, c = col - 4; r <= row && c <= col; r++, c++) {
            if (r < 0 || r >= MAX_ROW || c < 0 || c >= MAX_COL) {
                continue;
            }
            if (chessBoard[r][c] == chess
                    && chessBoard[r + 1][c + 1] == chess
                    && chessBoard[r + 2][c + 2] == chess
                    && chessBoard[r + 3][c + 3] == chess
                    && chessBoard[r + 4][c + 4] == chess) {
                done = true;
            }
        }
        // 4. 检查右对角线
        for (int r = row - 4, c = col + 4; r <= row && c >= col; r++, c--) {
            if (r < 0 || r >= MAX_ROW || c < 0 || c >= MAX_COL) {
                continue;
            }
            if (chessBoard[r][c] == chess
                    && chessBoard[r + 1][c - 1] == chess
                    && chessBoard[r + 2][c - 2] == chess
                    && chessBoard[r + 3][c - 3] == chess
                    && chessBoard[r + 4][c - 4] == chess) {
                done = true;
            }
        }
        if (!done) {
            return 0;
        }
        return chess == 1 ? user1.getUserId() : user2.getUserId();
    }
}